#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"
#include <asm/io.h>


static volatile unsigned int *CCM_CCGR1;
static volatile unsigned int *IOMUXC_SNVS_MUX_CTL_PAD_SNVS_TAMPER3;
static volatile unsigned int *GPIO5_GDIR;
static volatile unsigned int *GPIO5_DR;

/* 初始化LED, which-哪个LED */
static int board_demo_led_init (int which) 	   
{
	unsigned int val;
	/* 映射虚拟地址MMU */
	if(which == 0)
	{
		if (!CCM_CCGR1)
		{
			CCM_CCGR1                              = ioremap(0x20C406C,4);
			IOMUXC_SNVS_MUX_CTL_PAD_SNVS_TAMPER3   = ioremap(0x2290014,4);
			GPIO5_GDIR                             = ioremap(0x020AC000 + 0x04,4);
			GPIO5_DR                               = ioremap(0x20AC000 + 0,4);
		}
		
	}
	
	//printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
	
	/* 1、设置CCM,使能GPIO5 
	 * CCM_CCGR1 物理地址：20C_406C
	 * 默认是使能，这里不在设置
	 */
	
	
	/* 2、设置IOMUX，使能为GPIO5_IO03模式 
	 * IOMUXC_SNVS_MUX_CTL_PAD_SNVS_TAMPER3  物理地址：229_0014
	 */
	val = *IOMUXC_SNVS_MUX_CTL_PAD_SNVS_TAMPER3; //*取值运算符
	val &= ~(0xf);  //清空位
	val |= (5);     //打开位
	*IOMUXC_SNVS_MUX_CTL_PAD_SNVS_TAMPER3 = val;

	/* 3、设置GPIO引脚方向 ：输入还是输出(具体设置GPIO5_IO03为输出模式)
	 * GPIO5_GDIR 物理地址 020A_C000 +04
	 */
	val = *GPIO5_GDIR;
	val |= (1<<3);
	*GPIO5_GDIR = val;
	
	return 0;
}

/* 控制LED, which-哪个LED, status:1-亮,0-灭 */
static int board_demo_led_ctl (int which, char status)
{
	//printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
	 if(status)
	 {
	 	
		 /* 4、设置GPIO输出低电平 
		  * 物理地址 20A_C000 + 0
		  */
		*GPIO5_DR  &= ~(1<<3);
	}
	else 
	{
		/* 5、设置GPIO输出高电平 
		 * 物理地址 20A_C000 +0
		 */
		*GPIO5_DR |= (1<<3);

	}
	
	return 0;
}

/* 自定义驱动设备的结构体 */
static struct led_operations board_demo_led_opr = {
	.num = 1,
	.init = board_demo_led_init, //初始化LED
	.ctl  = board_demo_led_ctl,  //控制LED亮灭
};

/* 返回结构体指针 */
struct led_operations *get_board_led_opr(void)
{
	return &board_demo_led_opr;
}

